<?php

namespace Sys\Library;

/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2017/11/14
 * Time: 14:48
 */
class Dispatcher
{
    private static $config = array(
        'depr'          => '/',//分隔符
        'key'           => 'Controller',//关键字
        'var_path_info' => 's',//path-info的参数
        'var_class'     => 'c',//url c参数
        'var_method'    => 'm',//url m参数
        'class'         => 'index',//默认类名
        'method'        => 'index',//默认方法名
        'suffix'        => '.php',//后缀
        'vr_suffix'     => array('.html', '.htm', '.php', '.jsp', '.asp', '.py'),//允许虚似后缀存在
    );


    /**
     * 运行
     */
    public static function run()
    {
        if (config('app.dispatcher')) {
            self::$config = config('app.dispatcher');
        }
        self::_dispatch();
        self::_call();
    }

    /**
     * 调用方法 区分大小写
     */
    private static function _call()
    {
        $dir      = APP_PATH . 'Controllers/';
        $paths    = explode(self::$config['depr'], trim(__INFO__, self::$config['depr']));
        $class    = ucfirst($paths[0]) . self::$config['key'];
        $classObj = 'App\Controllers\\' . $class;
        $function = $paths[1];
        $path     = $dir . $class . self::$config['suffix'];
        if (is_file($path)) {
            if (!class_exists($classObj)) {
                sys_show('Class:' . $class . ' Not found');
            }
            $object = new $classObj;
            if (!method_exists($object, $function)) {
                sys_show('Method:' . $function . ' Not found');
            } else {
                $param_arr = self::_doParams($paths);
                $content = call_user_func_array(array($object, $function), $param_arr);
                if ($content === false) {
                    sys_show('Class:' . $class . ',Method:' . $function . ' Call Fail');
                } else {
                    if(is_array($content)) {
                        echo json_encode($content);
                    } else {
                        echo $content;
                    }
                }
            }
        } else {
            sys_show(str_replace(APP_ROOT, '', $path) . ' File Not Found...');
        }
    }

    /**
     * 路径处理支持三种
     * 一种：http://localhost/ask/index.php?c=class&m=method
     * 二种：http://localhost/ask/class/method 通过s=class/method
     * 三种: $_SERVER['PATH_INFO']
     */
    protected static function _dispatch()
    {
        $config = self::$config;
        if (isset($_GET[$config['var_class']]) && isset($_GET[$config['var_method']])) {
            $path = trim($_GET[$config['var_class']]) . $config['depr'] . trim($_GET[$config['var_method']]);
            unset($_GET[$config['var_class']], $_GET[$config['var_method']]);
        } else {
            //获取兼容模板 , 以/分隔
            //第一种 $_SERVER['PATH_INFO'];
            if (isset($_SERVER['REQUEST_URI'])) {
                $path = str_replace($_SERVER['SCRIPT_NAME'], '', $_SERVER['REQUEST_URI']);
            }//第二种　s模式
            elseif (isset($_GET[$config['var_path_info']])) {
                $path = trim($_GET[$config['var_path_info']]);
                unset($_GET[$config['var_path_info']]);
            }
            //处理 /
            $path = trim($path, $config['depr']);
            if (empty($path)) {
                $path = $config['class'] . $config['depr'] . $config['method'];
            }
            //给个默认的function index(){}
            if (strpos($path, $config['depr']) === false) {
                $path = $path . $config['depr'] . $config['method'];
            }
            //处理假.html .htm
            $path = str_replace($config['vr_suffix'], '', $path);
        }
        define('__INFO__', $path);
        $_SERVER['PATH_INFO'] = __INFO__;
    }


    /**
     * 处理参数并转换成$_GET
     * @param array $paths
     * @return array 结果
     */
    private static function _doParams($paths)
    {
        $params_list = array_slice($paths, 2);
        if (count($params_list) >= 2) {
            $params = array_chunk($params_list, 2);
            foreach ($params as $get) {
                $_GET[$get[0]] = $get[1];
            }
        }
        return $params_list;
    }
}